﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.Extensions.Logging;

namespace Communication.StreamResource.TCPImplementation;

//公共记录类型TcpConfiguration，继承自IConfiguration接口
public record TcpConfiguration(IPEndPoint Info) : IConfiguration
{
    /// <summary>
    ///     配置类型为Tcp
    /// </summary>
    public ConfigurationType Type => ConfigurationType.Tcp;

    /// <summary>
    ///     返回配置信息
    /// </summary>
    /// <param name="format"></param>
    /// <param name="formatProvider"></param>
    /// <returns></returns>
    public string ToString(string? format, IFormatProvider? formatProvider)
    {
        return $"{Type}-{Info}";
    }
}

//类TcpClientStreamResource，继承自IStreamResource接口
/// <summary>
///     TCP流资源 支持IPV4 和 IPV6
/// </summary>
/// <param name="info"></param>
/// <param name="logger"></param>
public class TcpClientStreamResource(TcpConfiguration info, ILogger logger) : IStreamResource
{
    /// <summary>
    ///     读取超时时间
    /// </summary>
    private int _readTimeout = 400;

    /// <summary>
    ///     写入超时时间
    /// </summary>
    private int _writeTimeout = 400;

    /// <summary>
    ///     TCP
    /// </summary>
    private Socket? Tcp { get; set; }

    /// <summary>
    ///     日志工厂
    /// </summary>
    public ILogger Logger { get; } = logger;


    /// <summary>
    ///     无限 timeout
    /// </summary>
    public int InfiniteTimeout => 0;

    //连接状态
    public bool Connected => Tcp?.Connected ?? false;

    /// <summary>
    ///     获取或设置读取超时时间
    /// </summary>
    public int ReadTimeout
    {
        get => _readTimeout;
        set
        {
            _readTimeout = value;
            if (Tcp is not null) Tcp.ReceiveTimeout = value;
        }
    }

    /// <summary>
    ///     获取或设置写入超时时间
    /// </summary>
    public int WriteTimeout
    {
        get => _writeTimeout;
        set
        {
            _writeTimeout = value;
            if (Tcp is not null) Tcp.SendTimeout = value;
        }
    }

    /// <summary>
    ///     丢弃入缓冲区
    /// </summary>
    public void DiscardInBuffer()
    {
        Logger.LogTrace(nameof(DiscardInBuffer));

        //port.DiscardOutBuffer();
        //port.DiscardInBuffer();
    }

    /// <summary>
    ///     释放资源
    /// </summary>
    public void Dispose()
    {
        // 判断Tcp是否为空
        if (Tcp is null) return;
        // 记录日志
        Logger.LogTrace(nameof(Dispose));
        Close();
        // 禁止垃圾回收
        GC.SuppressFinalize(this);
    }

    /// <summary>
    ///     读取数据
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="offset"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public int Read(byte[] buffer, int offset, int count)
    {
        return Tcp!.Receive(buffer, offset, count, SocketFlags.None);
    }


    /// <summary>
    ///     重置连接
    /// </summary>
    /// <returns></returns>
    public bool Reset()
    {
        // 记录日志
        Logger.LogTrace(nameof(Reset));
        // 如果已经连接，则直接返回true
        if (Tcp is not null && (!Tcp.Poll(1000, SelectMode.SelectRead) || Tcp.Available != 0) &&
            Tcp.Connected) return true;
        Close();
        // 创建一个新的Socket
        var tcp = new Socket(info.Info.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
        {
            // 关闭Nagle算法
            NoDelay = false,
            // 设置读取超时时间
            ReceiveTimeout = _readTimeout,
            // 设置发送超时时间
            SendTimeout = _writeTimeout
        };
        try
        {
            // 连接到服务器
            tcp.Connect(info.Info);
            Tcp = tcp;
        }
        catch (Exception)
        {
            tcp.Close();
            Thread.Sleep(1000);
            throw;
        }

        // 返回是否连接成功
        return Connected;
    }

    /// <summary>
    ///     写入数据
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="offset"></param>
    /// <param name="count"></param>
    public void Write(byte[] buffer, int offset, int count)
    {
        Tcp!.Send(buffer, offset, count, SocketFlags.None);
    }

    /// <summary>
    ///     返回配置信息
    /// </summary>
    /// <param name="format"></param>
    /// <param name="formatProvider"></param>
    /// <returns></returns>
    public string ToString(string? format, IFormatProvider? formatProvider)
    {
        return info.ToString(format, formatProvider);
    }

    public void Close()
    {
        // 销毁
        Tcp?.Shutdown(SocketShutdown.Both); //中止传输
        Tcp?.Disconnect(true);
        Tcp?.Close();
        Tcp = null;
    }
}